use std::sync::Arc;

use anyhow::Result;
use axum::response::IntoResponse;
use axum::Router;
use axum::routing::{delete, get, post, put};
use tokio::net::TcpListener;
use tokio::sync::Mutex;
use tower::ServiceBuilder;
use tower_http::catch_panic::CatchPanicLayer;
use tower_http::cors::{Any, CorsLayer};
use tower_http::services::ServeDir;
use tower_http::trace;
use tower_http::trace::TraceLayer;
use tracing::{info, Level};
use tracing::{Event, Subscriber};
use tracing_appender::non_blocking::{NonBlocking, WorkerGuard};
use tracing_appender::rolling;
use tracing_subscriber::{EnvFilter, Layer};
use tracing_subscriber::fmt;
use tracing_subscriber::fmt::{FmtContext, format, FormatEvent, FormatFields};
use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt;
use tracing_subscriber::Registry;
use tracing_subscriber::registry::LookupSpan;

use back_ground_task::back_task;
use controller::system_controller;
use middleware::exception_middleware;
use util::log_util;

use crate::app_state::AppState;
use crate::controller::{point_controller, point_group_controller, xun_you_controller};
use crate::controller::point_controller::{get_all_points, get_interpolation_simple, get_points_by_ids, get_points_by_names_ignore_case, get_td_tables};
use crate::middleware::machineindex_header_middleware::machine_index_header_middleware;
use crate::util_entity::config::{AppSettings, Config};

mod controller;
mod entity;
mod repo;
mod app_state;
mod dto;
mod util_entity;
mod middleware;
mod util;
mod back_ground_task;
mod huang_ling_task;

#[tokio::main]
async fn main() -> Result<()> {

    // 获取配置文件
    let (appsettings, config) = util::config_util::read_toml_config()?;
    let appsettings_clone = appsettings.clone();

    let _worker_guard = log_util::setup_logs();

    let app_state = Arc::new(Mutex::new(AppState::new(appsettings, config).await));
    // 后台任务
    back_task(app_state.clone()).await?;
    // 允许所有跨域
    let cors = CorsLayer::new()
        .allow_methods(Any) // 允许所有方法
        .allow_headers(Any) // 允许所有header
        .allow_origin(Any) // 允许所有origin
        ;

    let app = Router::new()
        .nest_service("/", ServeDir::new("./wwwroot"))
        .nest("/Cfg", controller::config_controller::route())
        .nest("/api/Point", point_controller::route())
        .nest("/api/PointGroup", point_group_controller::route())
        .nest("/api/system", system_controller::route())
        .nest("/api/JianPan", controller::jian_pan_controller::route())
        .nest("/api/XunYou", xun_you_controller::route())
        .layer(ServiceBuilder::new().layer(CatchPanicLayer::custom(exception_middleware::handle_exception)).into_inner())
        .layer(axum::middleware::from_fn(machine_index_header_middleware))
        .layer(TraceLayer::new_for_http()
                   .make_span_with(trace::DefaultMakeSpan::new()
                       .level(Level::INFO))
                   .on_response(trace::DefaultOnResponse::new()
                       .level(Level::INFO))
               ,
        )
        .layer(cors) // 这个中间件要放在最后面,越在代码底部的中间件越先执行
        .with_state(app_state)
        ;

    let addr = format!("0.0.0.0:{}", appsettings_clone.Port);
    info!("程序启动 listen on {}", addr);
    let listener = TcpListener::bind(addr).await.unwrap();
    axum::serve(listener, app.into_make_service())
        .await
        .unwrap();
    Ok(())
}
